/**
 * 支付服务
 * 处理第三方支付集成
 */
const { PrismaClient } = require('@prisma/client');
const crypto = require('crypto');
const axios = require('axios');

const prisma = new PrismaClient();

/**
 * 支付服务基类
 */
class PaymentService {
  constructor(config) {
    this.config = config;
  }

  /**
   * 创建支付订单
   * @param {Object} orderData - 订单数据
   * @returns {Promise<Object>} 支付结果
   */
  async createPayment(orderData) {
    throw new Error('子类必须实现 createPayment 方法');
  }

  /**
   * 查询支付状态
   * @param {string} transactionId - 交易ID
   * @returns {Promise<Object>} 支付状态
   */
  async queryPayment(transactionId) {
    throw new Error('子类必须实现 queryPayment 方法');
  }

  /**
   * 处理支付回调
   * @param {Object} callbackData - 回调数据
   * @returns {Promise<Object>} 处理结果
   */
  async handleCallback(callbackData) {
    throw new Error('子类必须实现 handleCallback 方法');
  }

  /**
   * 申请退款
   * @param {Object} refundData - 退款数据
   * @returns {Promise<Object>} 退款结果
   */
  async refund(refundData) {
    throw new Error('子类必须实现 refund 方法');
  }
}

/**
 * 微信支付服务
 */
class WechatPayService extends PaymentService {
  constructor(config) {
    super(config);
    this.baseUrl = 'https://api.mch.weixin.qq.com';
  }

  /**
   * 创建微信支付订单
   */
  async createPayment(orderData) {
    try {
      const { orderId, amount, description } = orderData;
      
      // 构建请求参数
      const params = {
        appid: this.config.appId,
        mch_id: this.config.mchId,
        nonce_str: this.generateNonceStr(),
        body: description,
        out_trade_no: orderId,
        total_fee: Math.round(amount * 100), // 转换为分
        spbill_create_ip: '127.0.0.1',
        notify_url: this.config.notifyUrl,
        trade_type: 'NATIVE' // 扫码支付
      };

      // 生成签名
      params.sign = this.generateSign(params);

      // 发送请求
      const response = await this.sendRequest('/pay/unifiedorder', params);
      
      if (response.return_code === 'SUCCESS' && response.result_code === 'SUCCESS') {
        return {
          success: true,
          prepayId: response.prepay_id,
          qrCode: response.code_url,
          transactionId: response.prepay_id
        };
      } else {
        return {
          success: false,
          error: response.err_code_des || response.return_msg
        };
      }
    } catch (error) {
      console.error('微信支付创建订单失败:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 查询微信支付状态
   */
  async queryPayment(transactionId) {
    try {
      const params = {
        appid: this.config.appId,
        mch_id: this.config.mchId,
        out_trade_no: transactionId,
        nonce_str: this.generateNonceStr()
      };

      params.sign = this.generateSign(params);
      const response = await this.sendRequest('/pay/orderquery', params);

      if (response.return_code === 'SUCCESS' && response.result_code === 'SUCCESS') {
        return {
          success: true,
          status: response.trade_state,
          paidTime: response.time_end,
          transactionId: response.transaction_id
        };
      } else {
        return {
          success: false,
          error: response.err_code_des || response.return_msg
        };
      }
    } catch (error) {
      console.error('查询微信支付状态失败:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 处理微信支付回调
   */
  async handleCallback(callbackData) {
    try {
      // 验证签名
      const sign = callbackData.sign;
      delete callbackData.sign;
      
      const expectedSign = this.generateSign(callbackData);
      if (sign !== expectedSign) {
        return {
          success: false,
          error: '签名验证失败'
        };
      }

      // 处理支付结果
      if (callbackData.return_code === 'SUCCESS' && callbackData.result_code === 'SUCCESS') {
        return {
          success: true,
          orderId: callbackData.out_trade_no,
          transactionId: callbackData.transaction_id,
          amount: callbackData.total_fee / 100,
          paidTime: callbackData.time_end
        };
      } else {
        return {
          success: false,
          error: callbackData.err_code_des || '支付失败'
        };
      }
    } catch (error) {
      console.error('处理微信支付回调失败:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 微信支付退款
   */
  async refund(refundData) {
    try {
      const { orderId, refundId, amount, refundAmount } = refundData;
      
      const params = {
        appid: this.config.appId,
        mch_id: this.config.mchId,
        nonce_str: this.generateNonceStr(),
        out_trade_no: orderId,
        out_refund_no: refundId,
        total_fee: Math.round(amount * 100),
        refund_fee: Math.round(refundAmount * 100)
      };

      params.sign = this.generateSign(params);
      const response = await this.sendRequest('/secapi/pay/refund', params, true);

      if (response.return_code === 'SUCCESS' && response.result_code === 'SUCCESS') {
        return {
          success: true,
          refundId: response.refund_id
        };
      } else {
        return {
          success: false,
          error: response.err_code_des || response.return_msg
        };
      }
    } catch (error) {
      console.error('微信支付退款失败:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * 生成随机字符串
   */
  generateNonceStr() {
    return crypto.randomBytes(16).toString('hex');
  }

  /**
   * 生成签名
   */
  generateSign(params) {
    const sortedKeys = Object.keys(params).sort();
    const stringA = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
    const stringSignTemp = `${stringA}&key=${this.config.apiKey}`;
    return crypto.createHash('md5').update(stringSignTemp).digest('hex').toUpperCase();
  }

  /**
   * 发送请求
   */
  async sendRequest(path, params, needCert = false) {
    const xml = this.buildXml(params);
    const config = {
      method: 'POST',
      url: `${this.baseUrl}${path}`,
      data: xml,
      headers: {
        'Content-Type': 'application/xml'
      }
    };

    if (needCert) {
      // 添加证书配置
      config.httpsAgent = new https.Agent({
        cert: fs.readFileSync(this.config.certPath),
        key: fs.readFileSync(this.config.keyPath)
      });
    }

    const response = await axios(config);
    return this.parseXml(response.data);
  }

  /**
   * 构建XML
   */
  buildXml(params) {
    let xml = '<xml>';
    Object.keys(params).forEach(key => {
      xml += `<${key}><![CDATA[${params[key]}]]></${key}>`;
    });
    xml += '</xml>';
    return xml;
  }

  /**
   * 解析XML
   */
  parseXml(xml) {
    // 简单的XML解析，实际项目中建议使用专业的XML解析库
    const result = {};
    const regex = /<(\w+)><!\[CDATA\[(.*?)\]\]><\/\1>/g;
    let match;
    while ((match = regex.exec(xml)) !== null) {
      result[match[1]] = match[2];
    }
    return result;
  }
}

/**
 * 支付宝支付服务
 */
class AlipayService extends PaymentService {
  constructor(config) {
    super(config);
    this.baseUrl = 'https://openapi.alipay.com/gateway.do';
  }

  async createPayment(orderData) {
    // 支付宝支付实现
    // 这里需要集成支付宝SDK
    return {
      success: true,
      qrCode: 'alipay_qr_code_url',
      transactionId: 'alipay_transaction_id'
    };
  }

  async queryPayment(transactionId) {
    // 查询支付宝支付状态
    return {
      success: true,
      status: 'TRADE_SUCCESS'
    };
  }

  async handleCallback(callbackData) {
    // 处理支付宝回调
    return {
      success: true,
      orderId: callbackData.out_trade_no
    };
  }

  async refund(refundData) {
    // 支付宝退款
    return {
      success: true,
      refundId: 'alipay_refund_id'
    };
  }
}

/**
 * 支付服务工厂
 */
class PaymentServiceFactory {
  static async createService(paymentMethod) {
    try {
      // 从数据库获取支付方式配置
      const config = await prisma.paymentMethod.findUnique({
        where: { id: paymentMethod }
      });

      if (!config || !config.status) {
        throw new Error(`支付方式 ${paymentMethod} 未配置或已禁用`);
      }

      const paymentConfig = {
        appId: config.appId,
        mchId: config.mchId,
        apiKey: config.apiKey,
        certPath: config.certPath,
        notifyUrl: config.notifyUrl,
        ...JSON.parse(config.config || '{}')
      };

      switch (paymentMethod) {
        case 'wechat':
          return new WechatPayService(paymentConfig);
        case 'alipay':
          return new AlipayService(paymentConfig);
        default:
          throw new Error(`不支持的支付方式: ${paymentMethod}`);
      }
    } catch (error) {
      console.error('创建支付服务失败:', error);
      throw error;
    }
  }
}

module.exports = {
  PaymentService,
  WechatPayService,
  AlipayService,
  PaymentServiceFactory
};
